<template>
    <el-container style="padding: 20px; max-width: 400px; margin: auto;">
        <el-button type="primary" @click="handleTest" style="margin-top: 10px;">
            测试
        </el-button>
    </el-container>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import type { FormInstance } from 'element-plus'
import { ElMessage } from 'element-plus'
import { color } from 'echarts'

const handleTest = () => {
    //可选属性
    //接口中的属性不全是必须的，有些只是在某些情况下存在或者不存在
    interface SquareConfig {
        color?: string,
        width?: number
    }
    function creatSquare(config: SquareConfig): { color: string, area: number } {
        let newSquare = {
            color: "white", area: 100
        };
        if (config.color) {
            newSquare.color = config.color
        }
        //如果正方形的长存在，则计算面积
        if (config.width) {
            newSquare.area = config.width * config.width
        }
        return newSquare
    }
    let mySquare = creatSquare({ color: "black" })

    //只读属性
    //一些对象只能在对象刚创建的时候修改其值，你可以在属性名前用readonly来指定只读属性
    interface Point {
        readonly x: number,
        readonly y: number
    }
    //然后通过赋值一个对象字面量来构造一个point 坐标，赋值后，x和y就不能再被改变了。
    let p1: Point = { x: 100, y: 200 }
    //尝试重新赋值p1
    // p1.x = 1000; // =>无法为“x”赋值，因为它是只读属性。

    //TS 具有ReadonlyArray<T> 类型 （泛型），她与 Array<T>相似，只是把所有可改变的方法去掉了，
    // 因此可以确保数组创建之后再也不能被改
    //a 为数字类型的数组
    let a: number[] = [1, 2, 3, 4]
    //ro 为只读类型的数字类型的数组
    let ro: ReadonlyArray<number> = a
    // ro.push(4)  //error
    // ro.length = 4  //error


    // readonly  VS  const
    //简要：作为变量使用的话使用 const  ;作为属性使用的话使用readonly

    //类型断言 as  some interface/type
    let mySquare1 = creatSquare({ width: 100, opacity: 0.5 } as SquareConfig)

    //函数类型
    //TS 中接口也可以描述函数类型
    //为了使用接口表示函数类型，需要给接口定义一个调用签名，就像是一个只有参数列表和返回值类型的函数定义，
    //参数列表里的每个参数都需要名字和类型
    interface SearchFunc {
        (source: string, subString: string): Boolean
    }
    //进行函数类型检查
    let mySearch: SearchFunc;
    mySearch = function (source: string, subString: string) {
        let result = source.search(subString);
        return result > 1
    }
    //对于函数类型的类型检查来说，函数的参数名不需要与接口中定义的名字相匹配，
    //只有对应位置上的参数类型是兼容的即可 比如
    let mySearch2: SearchFunc
    mySearch2 = function (src: string, sub: string) {
        let result = src.search(sub)
        return result > 1
    }


    //可索引的类型

}




</script>

<style scoped>
.el-input {
    width: 100%;
}
</style>
